﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PetaPoco;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching;
using PmSoft.DBContext;
using PmSoft.Exceptions;
using PmSoft.Repositories;

namespace Modules.System.Role
{
    [UseDI(ServiceLifetime.Scoped)]
    public class SysUserRoleRepository : Repository<SysUserRole, DefaultDbContext>
    {
        private readonly ILogger logger;
        private static readonly SysUserRoleComparer comparer = new SysUserRoleComparer();

        public SysUserRoleRepository(DefaultDbContext dbContext, IApplicationContext applicationContext, ILogger<SysUserRoleRepository> logger)
            : base(dbContext, applicationContext)
        {
            this.logger = logger;
        }

        /// <summary>
        /// 创建或更新角色与菜单关系数据
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="inUserRoles"></param>
        /// <exception cref="BusinessException"></exception>
        public void CreateOrUpdate(int userId, IEnumerable<SysUserRole> inUserRoles)
        {
            try
            {
                DbContext.BeginTransaction();

                var dbUserRoles = DbContext.Fetch<SysUserRole>("WHERE user_id=@0", userId);

                //删除
                var itemsToDelete = dbUserRoles.Except(inUserRoles, comparer).ToList();
                foreach (var item in itemsToDelete)
                {
                    Delete(item);
                }

                //更新
                var itemsToUpdate = dbUserRoles.Intersect(inUserRoles, comparer).ToList();
                foreach (var item in itemsToUpdate)
                {
                }

                //新增
                var itemsToAdd = inUserRoles.Except(dbUserRoles, comparer).ToList();
                foreach (var item in itemsToAdd)
                {
                    Insert(item);
                }
                DbContext.CompleteTransaction();
            }
            catch (Exception ex)
            {
                DbContext.AbortTransaction();
                string message = "角色与用户关系数据事务执行失败";
                logger.LogError(ex, message);
                throw new BusinessException(message);
            }
        }

        /// <summary>
        /// 根据用户ID获取关系集合
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public IEnumerable<SysUserRole> GetUserRolesByUserId(int userId)
        {
            int areaVersion = EntityCacheService.GetAreaVersion("UserId", userId);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"UserRolesByUserId:{userId}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("id")
                .From("sys_user_role")
                .Where("user_id=@0", userId);
                return sql;
            });
        }

        /// <summary>
        /// 根据角色ID获取关系集合
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public IEnumerable<SysUserRole> GetUserRolesByRoleId(int roleId)
        {
            int areaVersion = EntityCacheService.GetAreaVersion("RoleId", roleId);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"UserRolesByRoleId:{roleId}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("id")
                .From("sys_user_role")
                .Where("role_id=@0", roleId);
                return sql;
            });
        }
    }
}